package com.hxgis.oc.util;

import com.hxgis.oc.config.CmaConfig;
import com.hxgis.oc.config.OConfig;
import com.hxgis.oc.product.base.ProductFactory;
import com.hxgis.oc.product.base.ProductFactoryManager;
import com.hxgis.oc.product.file.DownloadTask;
import com.hxgis.oc.product.file.FileProductManager;
import com.hxgis.oc.util.ds.FileRecord;

import java.io.File;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public abstract class TimerBase extends TimerTask {
    protected LocalDateTime timeToday00;
    protected LocalDateTime lastClearTime;
    protected LocalDateTime nextUpdateTime;
    protected LocalDateTime timeCurrent;
    protected boolean initialized = false;
    protected boolean isUTC = false;
    protected boolean neverExpired = false;
    protected String dataSet;
    protected FileProductManager fileProductManager;
    int nextUpdateHour;
    int nextUpdateMinute;

    protected static void start(String name, TimerBase task) {
        new Timer(name,true).scheduleAtFixedRate(task, 0, 10 * 1000);
    }

    protected abstract DownloadTask createATask(long fid, File outputFile);

    public TimerBase(String ds,int h,int m){
        dataSet = ds;
        nextUpdateHour = h;
        nextUpdateMinute = m;
    }

    protected void updateTime(){
        LocalDateTime now = LocalDateTime.now();
        timeCurrent = now.minusSeconds(now.getSecond());
        timeToday00 = timeCurrent.minusMinutes(timeCurrent.getMinute()).minusHours(timeCurrent.getHour());

        if(isUTC){
            timeCurrent = timeCurrent.minusHours(8);
            timeToday00 = timeToday00.minusHours(8);
        }
        if(!initialized){
            initialized = true;
            lastClearTime = timeToday00;
            init();
        }
        else if(timeToday00.isAfter(lastClearTime)){
            lastClearTime = timeToday00;
            clear();
        }
    }

    protected boolean isTimeToUpdate() {
        boolean timeToUpdate = nextUpdateTime == null || timeCurrent.isAfter(nextUpdateTime);

        if(timeToUpdate){
            LocalDateTime dateTime = timeCurrent;
            if(nextUpdateHour > 0){
                //整点任务去掉分钟
                timeCurrent = timeCurrent.minusMinutes(timeCurrent.getMinute());
                dateTime = timeCurrent.plusHours(nextUpdateHour);
            }
            nextUpdateTime = dateTime.plusMinutes(nextUpdateMinute);
        }

        return timeToUpdate;
    }

    protected void clear(){
        Collection<ProductFactory> factoryList = ProductFactoryManager.getFactoryCollection();
        for(ProductFactory factory : factoryList){
            if(factory.accept(dataSet)){
                LocalDateTime clearTime = timeToday00;
                int keep = CmaConfig.getConfig().getKeepDays();
                if(keep > 1){
                    clearTime = clearTime.minusDays(keep - 1);
                }
                long clearTimeStamp = neverExpired ? 0 : OConfig.genTimeStampFid(clearTime);
                factory.clearInvalids(dataSet,clearTimeStamp);
            }
        }
    }

    void publishUndo(){
        int count1 = fileProductManager.count(dataSet);
        boolean needPublish = false;
        Collection<ProductFactory> factoryList = ProductFactoryManager.getFactoryCollection();
        for(ProductFactory factory : factoryList){
            if(factory.getClass() == FileProductManager.class){
                continue;
            }
            if(factory.accept(dataSet)){
                if(count1 != factory.count(dataSet)){
                    needPublish = true;
                    break;
                }
            }
        }

        if(needPublish){
            List<FileRecord> list = fileProductManager.getFileList(dataSet);
            list.forEach(record->{
                long fid = record.getFID();
                String fileName = record.getFileName();
                File file = fileProductManager.getFile(dataSet,fileName);
                DownloadTask task = createATask(fid,file);
                ProductFactoryManager.publish(task);
            });
        }
    }

    void init(){
        ProductFactoryManager.register(dataSet);
        if(fileProductManager == null){
            fileProductManager = (FileProductManager)ProductFactoryManager.getFactory(FileProductManager.getFactoryName());
        }
        clear();
        publishUndo();
    }

    @Override
    public void run() {
        updateTime();
    }
}
